[HBase]01 HBASE简介与环境搭建 一

HBase简介、HBase在大数据生态中的位置、HBase与HDFS、HBase使用场景、Hbase数据存储模型及与关系型数据库的区别、Hbase伪分布式集群安装、Hbase基础架构、HBase特点、RowKey的设计

Posted by 李玉坤 on 2017-09-14

HBase简介及其在大数据生态圈的位置

HBase简介

Apache HBase™是Hadoop数据库、分布式、可扩展、大数据存储。

使用Apache HBase™当你需要随机的,实时的大数据的读/写访问。这个项目的目标是在商品硬件集群上托管非常大的表——数十亿行X数百万列。Apache HBase是一个开源的、分布式的、版本化的、非关系型的数据库,模仿了谷歌的Bigtable: Chang等人为结构化数据构建的分布式存储系统。正如Bigtable利用了谷歌文件系统提供的分布式数据存储一样,Apache HBase在Hadoop和HDFS之上提供了类似于Bigtable的功能。

  • HBase是一个分布式的、面向列的开源数据库,

  • HBase在Hadoop之上提供了类似于Bigtable的能力

  • HBase不同于一般的关系数据库,它适合非结构化数据存储

    BigTable是什么?

  • BigTable是一种压缩的高性能的高可扩展性的基于Google文件系统gfs的数据库。用于存储大规模的结构化数据;在扩展性和性能方面有很大的优势。

    什么是面向列的数据库?

  • 它又叫列式数据库;把每一列的数据值放在一起进行存储;
    行式存储和列式存储:

HBase在大数据生态中的位置

  • HBase是Apache基金会顶级项目
  • HBase基于Hadoop的核心HDFS系统进行数据存储,类似于Hive
  • HBase可以存储超大数据并适合用来进行大数据的实时查询

HBase与HDFS

  • HBase建立在Hadoop文件系统之上,利用了Hadoop的文件系统的容错能力
  • HBase提供对数据的随机实时读/写访问功能
  • HBase内部使用哈希表,并存储索引,可将在HDFS文件中的数据进行快速查找

HBase使用场景

  • 瞬间写入量很大,常用数据库不好支撑或需要很高成本支撑的场景
  • 数据需要长久保存,且量会持久增长到比较大的场景
  • HBase不适用于有join,多级索引,表关系复杂的数据模型

Hbase数据存储模型及与关系型数据库的区别

CAP定理

对于一个分布式计算系统不可能全部满足以下三点:hbase为cp类型;它的每一行有单个的regionserver、rowkey、多版本标签等组合来保证行的一致性。

  • Consistency 一致性(所有节点在同一时间具有相同的数据)
  • Availability 可用性(保证每个请求不管成功或者失败都有响应,但不保证获取的数据为正确的数据)·
  • Partition tolerance 分区容错性(系统中任意信息的丢失或失败不会影响系统的继续运作,系统如果不能在某一个时限内达成数据一致性,就必须在上面两个操作之间做出选择)

ACID定义

Hbase不支持严格的ACID ;只支持单个的行ACID

  • 原子性
    整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
  • 一致性
    一个事务可以封装状态改变(除非它是一个只读的)。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
  • 隔离性
    隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
  • 持久性
    在事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。

Hbase核心概念

一行数据eg:row => rw1 column=cf1:q1, timestamp=1550351947916, value=val1

  • NameSpace:
    可以把NameSpace理解为RDBMS的“数据库”

  • Table:
    表名必须是能用在文件路径里的合法名字

  • Row:
    在表里面,每一行代表着一个数据对象,每一行都是以一个行键( Row Key )来进行唯一标识的,行键并没有什么特定的数据类型,以二进制的字节来存储

  • Column:
    HBase的列由Column family和Column qualifier组成 ,由冒号(:)进行进行间隔。比如family:qualifier

  • RowKey:
    可以唯一标识一行记录,不可被改变.

  • Column Family:
    在定义HBase表的时候需要提前设置好列族,表中所有的列都需要组织在列族里面
    一行数据同属于一个cf,一个table => N * cf , 一个cf => n * col

    cf =>

    {NAME => 'cf1', BLOOMFILTER => 'ROW', VERSIONS => '1', 
     IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'FALSE', 
     DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', 
     COMPRESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', 
     BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}
  • Column Qualifier:
    列族中的数据通过列标识来进行映射,可以理解为一个键值对,Column Qualifier就是Key.

  • Cell:
    每一个行键,列族和列标识共同组成一个单元
    cell: rk, cf:col, version

  • Timestamp:
    每个值都会有一个timestamp,作为该值特定版本的标识符

Hbase与传统关系型数据库的区别

1.动态列
2.存储数据形式
3.事物
4.分布式:可扩展的
5.支持的列多
6.kv存储
7.表之间的耦合性低
8.存在数据冗余
9.大数据量查询性能比较高
10.null不存的
11.本身二级索引不支持(rowkey scan: 全表 、范围),后续可以自己去做
12.trigger 触发器不支持
13.字段的支持格式单一(bytes)


传统存储:

Hbase归类存储:

Hbase数据模型

可想象为大的map;详见下图:

访问数据步骤如下图:

Hbase伪分布式集群安装

前置条件安装并且启动HDFS

  1. 下载HBase 传到服务器并且解压【hbase-1.2.0-cdh5.7.0】
    http://archive.cloudera.com/cdh5/cdh/5/
  2. 配置文件
    把$Hadoop_Home/etc/hadoop/hdfs-site.xml和core.site.xml拷贝到$HBase_home/conf下

或者进入$HBase_home/conf目录下 建立软连接
ln -s $Hadoop_Home/etc/hadoop/hdfs-site.xml hdfs-site.xml
ln -s $Hadoop_Home/etc/hadoop/core-site.xml core-site.xml

  • 配置HBase_home/conf/hbase-env.sh
    1
    2
    3
    export JAVA_HOME=/home/hadoop/app/jdk1.7.0_79
    export HBASE_PID_DIR=/home/hadoop/tmp
    export HBASE_MANAGES_ZK=false
  • 配置HBase_home/conf/hbase-site.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<property>
<name>hbase.rootdir</name>  --hbase持久保存的目录
<value>hdfs://hadoop:8020/hbase</value>
</property>

<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>zk的data目录路径</value>
</property>

<property>
<name>hbase.cluster.distributed</name> --是否以集群方式运行(虽然一个节点也可配置为true)
<value>true</value>
</property>

常用配置参数详解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<configuration>
<!--hbase.rootdir的前端与$HADOOP_HOME/conf/core-site.xml的fs.defaultFS一致 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hadoop:9000/hbase</value>
</property>
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>

<!--本地文件系统的临时文件夹。可以修改到一个更为持久的目录上。(/tmp会在重启时清除) -->
<property>
<name>hbase.tmp.dir</name>
<value>/home/hadoop/tmp/hbase</value>
</property>

<!--如果只设置单个 Hmaster,那么 hbase.master 属性参数需要设置为 master5:60000 (主机名:60000) -->
<!--如果要设置多个 Hmaster,那么我们只需要提供端口 60000,因为选择真正的 master 的事情会有 zookeeper 去处理 -->
<property>
<name>hbase.master</name>
<value>60000</value>
</property>

<!--这个参数用户设置 ZooKeeper 快照的存储位置,默认值为 /tmp,显然在重启的时候会清空。因为笔者的 ZooKeeper 是独立安装的,所以这里路径是指向了 $ZOOKEEPER_HOME/conf/zoo.cfg 中 dataDir 所设定的位置 -->
<property>
<name>hbase.zookeeper.property.dataDir</name>
<value>/home/hadoop/tmp/zookeeper</value>
</property>

<property>
<name>hbase.zookeeper.quorum</name>
<value>ruozedata001</value>
</property>
<!--表示客户端连接 ZooKeeper 的端口 -->
<property>
<name>hbase.zookeeper.property.clientPort</name>
<value>2181</value>
</property>
<!--ZooKeeper 会话超时。Hbase 把这个值传递改 zk 集群,向它推荐一个会话的最大超时时间 -->
<property>
<name>zookeeper.session.timeout</name>
<value>120000</value>
</property>

<!--当 regionserver 遇到 ZooKeeper session expired , regionserver 将选择 restart 而不是 abort -->
<property>
<name>hbase.regionserver.restart.on.zk.expire</name>
<value>true</value>
</property>

<property>
<name>hbase.online.schema.update.enable</name>
<value>true</value>
</property>

<property>
<name>hbase.coprocessor.abortonerror</name>
<value>false</value>
</property>
</configuration>
  1. 启动和停止
    hbase_home/bin/start-hbase.sh
    jps检查:
     HQuorumPeer
     HRegionServer
     HMaster
     NameNode
     SecondaryNameNode
     DataNode
    网页链接检查:
    http://hadoop:60010

注意:如果重新部署或者升级,需要删除下列东东

1
2
3
4
5
6
7
[hadoop@hadoop bin]$ ./stop-hbase.sh 
hdfs的hbase文件
[hadoop@hadoop ~]$ hdfs dfs -rm -r -skipTrash /hbase
hbase的元数据
[zk: hadoop:2181(CONNECTED) 0] ls /
[zookeeper, hbase]
[zk: hadoop:2181(CONNECTED) 1] rmr /hbase

Hbase基础架构

  • Hmaster
    • hmaster是hbase主/从集群架构中的中央节点
    • Hmaster将region分配给regionserver, 协调regionserver的
      负载并维护集群的状态
    • 维护表和region的元数据, 不参与数据的输入/输出过程
  • RegionServer
    • 维护hmaster分配给它的region, 处理对这些region的io请求
    • 负责切分正在运行过程中变的过大的region
  • Zookeeper
    • Zookeeper是集群的协调器
    • Hmaster启动将系统表加载到zookeeper
    • 提供hbase Regionserver状态信息

HBase特点

  • 线性和模块化的可伸缩性。
  • 严格一致的读写。
  • 自动和可配置的分片表
  • 区域服务器之间的自动故障转移支持。
  • 使用Apache HBase表支持Hadoop MapReduce作业的方便基类。
  • 易于使用Java API进行客户端访问。
  • 用于实时查询的块缓存和布鲁姆过滤器。
  • 查询谓词通过服务器端过滤器向下推
  • 节俭网关和支持XML、Protobuf和二进制数据编码选项的rest式Web服务
  • 可扩展的基于jruby的(JIRB) shell
  • 支持通过Hadoop metrics子系统将指标导出到文件或Ganglia或通过JMX

RowKey的设计

如果不设计rowkey 默认一个表只有一个region

盐表

1
2
3
4
5
6
7
8
9
10
11
create 'FileTable','fileInfo', SPLITS => ['a', 'b', 'c', 'd']  
一共 4+1=5区域:~-a, a-b , b-c , c-d , d-~
region [startkey,endkey)

put 'FileTable' , '001','order:ordersum','200' 区域:~-a
put 'FileTable' , 'a-002','order:ordersum','200' 区域:a-b
put 'FileTable' , 'a-xxxxx','order:ordersum','200' 区域:a-b 加如有1亿条 区域:a-b的数据
put 'FileTable' , 'c-002','order:ordersum','200' 区域:c-d
put 'FileTable' , 'g-002','order:ordersum','200' 区域:d-~
a对应的region 所在比如 hadoop机器 繁忙
其他机器闲 造成数据写入热点 读写不均匀

改进后:

1
2
3
4
5
6
7
8
9
10
create 'FileTable', 'order', SPLITS => ['1', '2', '3', '4']

~ 1
1 2
2 3
3 4
4 ~

rowkey: 10001--> 1 2
99999--> 4 ~

这种加盐的方式可简单理解为:固定长度随机数+rowkey原有值==》新rowkey 去存储

好处:通过随机数 提高写的吞吐量 保证 数据在 所有region中 是均衡的

缺点: 因为添加的是随机数,基于原有的rk查询时 无法知道随机数是什么,那么就需要去各个region去查找,必然增加读的开销

hbase天然的 写的优势大 读的优势少 加盐方式适用于业务场景 重写轻读

hash

1
2
3
4
5
6
7
8
9
10
11
12
rowKey, Value
md5(1)-》1==》 95f111a-1 , name=小明
md5(2)-》2==》 6gggda2-2 , name=小王
md5(3)-》3==》 ijaq111-3 , name=小李

create 'FileTable', 'order', {NUMREGIONS => 5, SPLITALGO => 'HexStringSplit'}
自带的hash方式:SPLITALGO => 'HexStringSplit'
分5个分区:NUMREGIONS => 5

put 'FileTable' , '1','order:ordersum','200'
put 'FileTable' , 'abc123-1','order:ordersum','200'
put 'FileTable' , 'dfg333-2','order:ordersum','200'

注意选取的哈希算法要必须需要转换唯一
即:算法选择必须是同一行rk hash之后值是一样的,不要不一样
例一:1–》abc123 1–》 dfg777 一对多转换不行
例二:1–》abc123 唯一可行

hash方式:基于rk的完整部分或者部分数据 进行hash,hash的值作为前缀;

好处: 数据也可以均匀的分散到各个region,就是分散到各个集群节点上,避免了热点,天然的优势支持 get操作,但是前提你要知道原rk值和rowkey拼接结构

坏处: 基于rk的完整部分进行hash,不利于scan操作比如前缀过滤,因为数据在原有的rowkey的自然顺序上被打乱了,需要多个region 取数